/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-03-12     Bernard      first version
 * 2006-05-27     Bernard      add support for same priority thread schedule
 * 2006-08-10     Bernard      remove the last rt_schedule in rt_tick_increase
 * 2010-03-08     Bernard      remove rt_passed_second
 * 2010-05-20     Bernard      fix the tick exceeds the maximum limits
 * 2010-07-13     Bernard      fix rt_tick_from_millisecond issue found by kuronca
 * 2011-06-26     Bernard      add rt_tick_set function.
 * 2018-11-22     Jesven       add per cpu tick
 */

#include <rthw.h>
#include <rtthread.h>

#ifdef RT_USING_SMP
#define rt_tick rt_cpu_index(0)->tick
#else
static rt_tick_t rt_tick = 0;
#endif

/**
 * This function will init system tick and set it to zero.
 * @ingroup SystemInit
 *
 * @deprecated since 1.1.0, this function does not need to be invoked
 * in the system initialization.
 */
void rt_system_tick_init(void)
{
}

/**
 * @addtogroup Clock
 */

/**@{*/

/**
 * This function will return current tick from operating system startup
 *
 * @return current tick
 */
rt_tick_t rt_tick_get(void)
{
    /* return the global tick */
    return rt_tick;
}
RTM_EXPORT(rt_tick_get);

/**
 * This function will set current tick
 */
void rt_tick_set(rt_tick_t tick)
{
    rt_base_t level;

    level = rt_hw_interrupt_disable();
    rt_tick = tick;
    rt_hw_interrupt_enable(level);
}

/**
 * This function will notify kernel there is one tick passed. Normally,
 * this function is invoked by clock ISR.
 */
void rt_tick_increase(void)
{
    struct rt_thread *thread;

    /* increase the global tick */
#ifdef RT_USING_SMP
    rt_cpu_self()->tick ++;
#else
    ++ rt_tick;
#endif

#if 0
extern rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
extern rt_uint32_t rt_thread_ready_priority_group;
rt_uint32_t rt_thread_ready_priority_group_tmp=rt_thread_ready_priority_group;
rt_uint32_t highest_ready_priority;
while (rt_thread_ready_priority_group_tmp)
{
      highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group_tmp) - 1;
       rt_list_t *l;
    rt_list_for_each(l, &rt_thread_priority_table[highest_ready_priority])
    {
        thread = rt_list_entry(l,
                               struct rt_thread,
                               tlist);
        if(((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND) && (thread->remaining_tick >= 0))
        {  
            if(thread->remaining_tick == 0)
            {
                thread->remaining_tick = thread->init_tick;
                rt_thread_timeout(thread);
                continue;
            }
            thread->remaining_tick --;
        }
    }
    rt_thread_ready_priority_group_tmp &=~(1<<highest_ready_priority);

   
}
 /* code */
    #else
    rt_timer_check();
    #endif


    // /* check time slice */
    // thread = rt_thread_self();

    // -- thread->remaining_tick;
    // if (thread->remaining_tick == 0)
    // {
    //     /* change to initialized tick */
    //     thread->remaining_tick = thread->init_tick;

    //     /* yield */
    //     rt_thread_yield();
    // }

    /* check timer */
    // rt_timer_check();
}

/**
 * This function will calculate the tick from millisecond.
 *
 * @param ms the specified millisecond
 *           - Negative Number wait forever
 *           - Zero not wait
 *           - Max 0x7fffffff
 *
 * @return the calculated tick
 */
rt_tick_t rt_tick_from_millisecond(rt_int32_t ms)
{
    rt_tick_t tick;

    if (ms < 0)
    {
        tick = (rt_tick_t)RT_WAITING_FOREVER;
    }
    else
    {
        tick = RT_TICK_PER_SECOND * (ms / 1000);
        tick += (RT_TICK_PER_SECOND * (ms % 1000) + 999) / 1000;
    }
    
    /* return the calculated tick */
    return tick;
}
RTM_EXPORT(rt_tick_from_millisecond);

/**@}*/

